package com.lab303.powerproject.service.impl;

import com.lab303.powerproject.entity.*;
import com.lab303.powerproject.pojo.CustomAtlasDevice;
import com.lab303.powerproject.pojo.CustomDevice;
import com.lab303.powerproject.pojo.CustomDeviceListObject;
import com.lab303.powerproject.repository.DeviceRepository;
import com.lab303.powerproject.repository.GraphInfoRepository;
import com.lab303.powerproject.repository.RelationshipRepository;
import com.lab303.powerproject.service.DeviceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
public class DeviceServiceImpl implements DeviceService {

    @Autowired
    private DeviceRepository deviceRepository;

    @Autowired
    private RelationshipRepository relationshipRepository;

    @Autowired
    private GraphInfoRepository graphInfoRepository;

    @Override
    public List getAllDevices() {
        List<Device> all = deviceRepository.findAll();
        List<CustomDeviceListObject> list = new ArrayList<>();
        for (Device device:all){
            Optional<GraphInfo> graphInfo = graphInfoRepository.findById(device.getGraphId());
            list.add(new CustomDeviceListObject(device.getDeviceId(),device.getDevCode(),device.getDeviceName(),graphInfo.get().getGraphName(),device.getBatteryCode(),device.getTemperatureCode()));
        }
        return list;
    }

    @Override
    public void deleteDeviceById(Integer deviceId) {
        deviceRepository.deleteById(deviceId);
        List<Relationship> deviceFromEquals = relationshipRepository.findRelationshipsByDeviceFromEquals(deviceId);
        List<Relationship> deviceToEquals = relationshipRepository.findRelationshipsByDeviceToEquals(deviceId);
        if (deviceFromEquals.size()>0){
            relationshipRepository.deleteInBatch(deviceFromEquals);
        }
        if (deviceToEquals.size()>0){
            relationshipRepository.deleteInBatch(deviceToEquals);
        }
    }

    @Override
    public Device findDeviceById(Integer id) {
        Device device = deviceRepository.findById(id).orElse(null);
        if(device!=null){
            for(AdditionalProperties p : device.getPropertyList()){
                p.setDevice(null);
            }
        }
        return device;
    }

    @Override
    public List<CustomDevice> findDevices() {
        return deviceRepository.selectAllDevices();
    }

    @Override
    public List findDeviceByTypeId(Integer typeId) {
        List<Device> devices = deviceRepository.selectDevicesByTypeId(typeId);
        List<CustomDeviceListObject> list = new ArrayList<>();
        for (Device device:devices){
            Optional<GraphInfo> graphInfo = graphInfoRepository.findById(device.getGraphId());
            list.add(new CustomDeviceListObject(device.getDeviceId(),device.getDevCode(),device.getDeviceName(),graphInfo.get().getGraphName(),device.getBatteryCode(),device.getTemperatureCode()));
        }
        return list;
    }

    @Override
    public void saveAndUpdateProperties(Device device) {
        deviceRepository.save(device);
    }

    @Override
    public Device saveAndFlush(Device device) {
        return deviceRepository.saveAndFlush(device);
    }



    @Override
    public int getDeviceNumber(Integer deviceType) {
        Device device = new Device();
        DeviceType deviceType1 = new DeviceType();
        deviceType1.setTypeId(deviceType);
        device.setDeviceType(deviceType1);
        Example<Device> deviceExample = Example.of(device);
        return (int) deviceRepository.count(deviceExample);
    }

    @Override
    public boolean checkDeviceName(String deviceName) {
        List<Device> equals = deviceRepository.findDevicesByDeviceNameEquals(deviceName);
        if (equals==null||equals.size()==0)
            return true;
        else
            return false;
    }

    @Override
    public List getAllAtlasDevice() {
        List<CustomAtlasDevice> atlasDevices = deviceRepository.selectAtlasDevice();
        return atlasDevices.size()==0?null:atlasDevices;
    }

    @Override
    public CustomAtlasDevice findCustomAtlasDeviceById(Integer deviceId) {
        CustomAtlasDevice customAtlasDevice = deviceRepository.selectAtlasDeviceByDeviceId(deviceId);
        return customAtlasDevice;
    }

    @Override
    @Transactional
    public void updateDeviceCoordinates(List<Device> list) {
        for (Device device:list){
            deviceRepository.updateDeviceCoordinates(device.getxCoordinates(),device.getyCoordinates(),device.getDeviceId());
        }
    }

    @Override
    public void updateDeviceCoordinatesAndIsInGraph(List<Device> list) {
        for (Device device:list){
            deviceRepository.updateDeviceCoordinatesAndIsInGraph(device.getxCoordinates(),device.getyCoordinates(),device.getIsInGraph(),device.getDeviceId());
        }
    }

    @Override
    public List getDevicesByGraphId(Integer graphId) {
        return deviceRepository.findDevicesByGraphId(graphId);
    }

    @Override
    public CustomDevice findCustomDeviceById(Integer deviceId) {
        return deviceRepository.selectCustomDevice(deviceId);
    }

    @Override
    public List<Device> findDevicesByGraphId(Integer graphId) {
        List<Device> graphIdEquals = deviceRepository.findDevicesByGraphIdEquals(graphId);
        return graphIdEquals;
    }

    @Override
    public List getDeviceList() {
        return deviceRepository.findAll();
    }

    @Override
    public List getAtlasDevicesByGraphId(Integer graphId) {
        return deviceRepository.selectAtlasDeviceByGraphId(graphId);
    }

    @Override
    public void deleteDeviceByGraphId(Integer graphId) {
        deviceRepository.deleteDevicesByGraphId(graphId);
    }

    @Override
    public List findDevicesByGraphIdAnIsInGraph(Integer graphId,Integer isInGraph) {
        List<Device> devices = deviceRepository.findDevicesByGraphIdAndIsInGraph(graphId, isInGraph);
        return devices;
    }


}
